----------------------------------------------------------------------
-- This file is part of LURE.
--
-- LURE is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.

-- LURE is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.

-- You should have received a copy of the GNU General Public License
-- along with LURE.  If not, see <http://www.gnu.org/licenses/>.
---------------------------------------------------------------------

-- needs lib.lua

---------------------------------------------------------------------
The.all = "._=all=_."

Cell = Object:new{name="",pos=0,isKlass=false,isIgnored=false}

--
-- Sym
--
Sym = Cell:new{counts={}}

function Sym:add(x,at) 
   at = inc(self.counts,at,x); return x;  end

function Sym:compile(x) -- compile fails if x invalid
   return x,true
end

function Sym:dist(sym1,sym2)
   if (sym1==sym2) then return 0 else return 1 end
end

function Sym:halfway(sym1,sym2)
   if (sym1==sym2) then return sym1
   elseif math.random(100000) >= 50000 then 
      return sym1
   else return sym2
end end

-- first read, taste it. place raw type into row
-- second read, swallow it. place it into cooked
--
-- Num
--
Num = Cell:new{max={}, min ={},sum={},sumSq={},n={}}

-- taste: tentative peek. if ok, passed to raw
function Num:compile(x)
   x = tonumber(x)
   if x then return x,true else error(x .. "not a number") end
end
      
function Num:add(x,at)
   at= at or The.all
   inc(self.n,at)
   local max = self.max[at]
   if max then
      if x > max  then self.max[at] = x end
   else
      self.max[at]=x
   end
   local min = self.min[at]
   if min then
      if x < min then self.min[at] = x end
   else
      self.min[at]= x
   end
   inc(self.sum  , at, x)
   inc(self.sumSq, at, x*x)
   return x
end

function Num:mean(at)
   at = at or The.all
   return self.sum[at]/self.n[a]
end

function Num:sd(at)
   at = at or The.all
   return sd(self.sum[at],self.sumSq[at],self.n[at])
end

function Num:dist(num1,num2) -- assumes normalized nums
   return num1 - num2
end

function Num:halfway(num1,num2)
   return (num1 - num2) / 2
end

function Num:normalize(n,at)
   at = at or The.all
   return (n - self.min[at]) / (self.max[at] - self.min[at])
end

function Num:nbins(n,bins,at)
   at = atm or The.all
   bins = bins or The.bins
   local bin = (n - self.min[at]) / ((self.max[at] - self.min[at]) / bins)
   bin = 1 + math.floor(bin)
   if (bin > bins) then bin = bins end
   return bin
end




